package org.rain.core.querygen;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import jakarta.servlet.http.HttpServletRequest;
import org.rain.core.querygen.token.QueryTokenizer;
import org.rain.core.querygen.token.Token;
import org.rain.core.util.ReqUtil;
import org.rain.core.util.Springs;
import org.springframework.context.ApplicationContext;
import org.springframework.core.Ordered;

import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.Map;

/**
 * created by yangtong on 2025/4/7 16:04:54
 * <br/>
 * QueryWrapper生成器
 */
public class QueryWrapperGenerate {

    private static List<AbsQueryCondition> conditions;
    /**
     * 忽略请求中的这些字段
     */
    private static List<String> ignoreFields = List.of("pageNo", "pageSize");

    public static <T> QueryWrapper<T> init(Object entity) {
        HttpServletRequest request = ReqUtil.getRequest();
        String queryString = request.getQueryString();
        QueryWrapper<T> queryWrapper = new QueryWrapper<>();
        if (queryString != null) {
            List<Token> tokens = Arrays.stream(queryString.split("&")).filter(i -> {
                String key = i.split("=")[0];
                return !ignoreFields.contains(key);
            }).map(QueryTokenizer::tokenize).toList();

            for (Token token : tokens) {
                for (AbsQueryCondition queryCondition : getConditions()) {
                    if (queryCondition.isMatch(token)) {
                        queryCondition.genQueryWrapper(queryWrapper, token);
                        break;
                    }
                }
            }
        }

        return queryWrapper;
    }

    private static List<AbsQueryCondition> getConditions() {
        if (conditions == null) {
            ApplicationContext context = Springs.getApplicationContext();
            Map<String, AbsQueryCondition> queryConditions = context.getBeansOfType(AbsQueryCondition.class);
            conditions = queryConditions.values().stream().sorted(Comparator.comparingInt(Ordered::getOrder)).toList();
        }
        return conditions;
    }

}
